home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / MACSHELL / MS1 / SHELL_SO / SCRIPT.C < prev    next >
Text File  |  1992-12-02  |  19KB  |  789 lines

  1. /*
  2.  *    MacShell Source File
  3.  *
  4.  *    Copyright (c) 1989, 1990, 1991, 1992  Suick Bay Technologies.  All rights reserved.
  5.  *
  6.  *
  7.  *    RESTRICTIONS ON MacShell program and source code.
  8.  *
  9.  *    Ñ╩MacShell¬ is a product of Suick Bay Technologies and is provided for
  10.  *    restricted use by the owner of the CDROM "Disk to the future II".
  11.  *
  12.  *    Ñ╩No permission is granted for any commercial use without the written
  13.  *    consent of the Suick Bay Technologies.
  14.  *
  15.  *    Ñ╩No permission is granted for any redistribution of any kind use without
  16.  *    the written consent of the Suick Bay Technologies.
  17.  *
  18.  *    Ñ╩Permission is granted to use this for any personal noncommercial use.
  19.  *
  20.  *    Ñ╩You may not distribute source or executable code at all, nor may you 
  21.  *    distribute it with or within a commercial product without the written
  22.  *    consent of the Suick Bay Technologies.  Please send modifications to 
  23.  *    the author for inclusion in updates to the program.  Thanks.
  24.  *
  25.  *
  26.  *    MacShell¬ IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
  27.  *    WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
  28.  *    PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
  29.  *
  30.  *    SUICK BAY TECHNOLOGIES SHALL HAVE NO LIABILITY WITH RESPECT TO THE
  31.  *    INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY MACSHELL
  32.  *    OR ANY PART THEREOF. 
  33.  *
  34.  *    In no event will Suick Bay Technologies be liable for any lost revenue
  35.  *    or profits or other special, indirect and consequential damages, even if
  36.  *    Suick Bay Technologies has been advised of the possibility of such damages.
  37.  *
  38.  *    Suick Bay Technologies can be reached at:
  39.  *    
  40.  *    8768 Cottonwood lane
  41.  *    Maple Grove, MN 55369
  42.  *    Voice: (612) 425-7025
  43.  *    AppleLink: D5233
  44.  *    
  45.  *
  46.  *    No parts of this software may be reproduced or stored in a
  47.  *    retrieval system or transmitted in any form, or any means,
  48.  *    electronic, mechanical, photocopying, recording or otherwise,
  49.  *    without the prior written permission of Suick Bay Technologies.
  50.  *    
  51.  *    Spread the word and not the disk.
  52.  *    
  53.  *    SPK 012290    :    Initial
  54.  */
  55.  
  56. /*******************************************************************
  57.  *
  58.  * Script control file
  59.  *
  60.     Before a command is executed the following substitutions occur
  61.     
  62.         Ñ    Parameter substitution (shell vars)
  63.         Ñ    Command 'Quote' substitution ('pwd')
  64.         Ñ    Blank interpretation
  65.         Ñ    File name generation (*?[╔])
  66.     
  67.     Shell vars
  68.     
  69.         $?        Exit status (return code) of the last command
  70.         $#        number of parameters (arguments)
  71.         $$        Process number of this shell
  72.     
  73.         $0        The name of the command procedure being executed
  74.         $1        argument 1
  75.         $2        argument 2
  76.         $3        argument 3 ... etc.
  77.     
  78.     Control Flow
  79.     
  80.         while command-list
  81.         do command-list
  82.         done
  83.         
  84.         until command-list
  85.         do command-list
  86.         done
  87.         
  88.         if command-list
  89.         then command-list
  90.         [ elif command-list then command-list ]
  91.         [ else command-list ]
  92.         fi
  93.         
  94.         break        Exit from enclosing for or while loop
  95.         continue    do next iteration of for or while
  96.         
  97.  
  98.  *******************************************************************/
  99.  
  100. #define        _SCRIPTDEBUG
  101. #define        _SDB
  102.  
  103. #include    "System.h"
  104. #include    "Parse.h"
  105. #include    "Proc.h"
  106. #include    "Path.h"
  107. #include    "Shell.h"
  108.  
  109. static    Boolean        verbose;        /* echo commands as they are executed in the script */
  110. extern    Boolean        StdOutAppend;    /* flag for appending std out file */
  111.  
  112. /*******************************************************************/
  113.  
  114. Boolean        DoSCRIPTLine( WHandle ShellWh, int16 ProcID, char *string )
  115. {
  116. char        *cp, buf[ 64 ], stdInFile[ 64 ], stdOutFile[ 64 ];
  117. int16        currProcSlot, lastProcSlot, pipeFromLast, pipeToNext, pipeErr,
  118.             i, ioOk, err,
  119.             cmdc,
  120.             tokenType, lastToken,
  121.             ProcDataAvail,
  122.             parseErr = 0,
  123.             inProc, outProc, errProc;
  124. ShellWindRec    **MyShell;
  125.  
  126. /*
  127.  *    Command execution vars
  128.  */
  129. ProcPtr        theCommand;
  130. int16        needsStdIn;
  131.  
  132.     if( UserAbort() )
  133.         return( FALSE );
  134.  
  135.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  136.  
  137.     lastProcSlot = CL_PROCID;
  138.     if( ShellWh && string )
  139.         {
  140.         cp = string;
  141.         
  142. #ifdef    SCRIPTDEBUG
  143.         printf( "DoSCRIPTLine : '%s'\n", string );
  144. #endif
  145.         currProcSlot = GetProcSlot( ShellWh );
  146.         
  147.         if( currProcSlot == UNKNOWN )
  148.             {
  149.             ShellError( se_noProcSlots );    
  150.             return( FALSE );
  151.             }
  152.         else    /* Initialize the Proc */
  153.             {
  154.             (**MyShell).Proc[ currProcSlot ].argc         = 0;
  155.             cmdc = 0;
  156.             
  157.             (**MyShell).StdOutAppend     = FALSE;
  158.             lastToken         = UNKNOWN;
  159.             ProcDataAvail     = FALSE;
  160.             lastProcSlot     = ProcID;
  161.             pipeFromLast     = FALSE;
  162.             pipeToNext         = FALSE;
  163.             pipeErr            = FALSE;
  164.             ioOk            = FALSE;
  165.             stdInFile[ 0 ]     = '\0';
  166.             stdOutFile[ 0 ]    = '\0';
  167.             }
  168.  
  169.         inProc     = STDIN_PROCID;
  170.         outProc = (**MyShell).Proc[ ProcID ].StdOutProcID;
  171.         errProc = (**MyShell).Proc[ ProcID ].StdErrProcID;
  172.         
  173.         while( cp && !UserAbort() )
  174.             {
  175.             cp = GetShellToken( cp, buf, &tokenType );
  176.             parseErr = 0;
  177.             CursorWait();
  178.                     
  179.             switch( tokenType )
  180.                 {
  181.                 case    tkn_andf        :    /* '&&'            */
  182.                 case    tkn_orf            :    /* '||'            */
  183.                 case    tkn_background    :    /* '&'            */
  184.                     break;
  185.  
  186.                 case    tkn_pipeOutErr    :    /* '|&'            */
  187.                     pipeErr = TRUE;
  188.                 case    tkn_pipe        :    /* '|'            */
  189.                     pipeToNext = TRUE;
  190.                 
  191.                 case    tkn_separator    :    /* ';'            */
  192.                 case    tkn_eol            :    
  193. Execute:
  194.                      if( tokenType == tkn_eol && verbose )
  195.                         procPrintf( ShellWh, ProcID, "%s%s",
  196.                             ShellGetVar( ShellWh, "PS1" ), string );
  197.                         
  198.                     if( ProcDataAvail )
  199.                         {
  200. /*    Start the process    
  201.  */                        char    command[ 256 ];
  202.                         
  203.                         GetArgv( ShellWh, currProcSlot, 0, command );
  204.  
  205.                          if( GetCommandInfo( command, &theCommand, &needsStdIn ) )
  206.                              {
  207. forceCommand :
  208.                             ShellSetVar( ShellWh, "COMMAND", string );
  209.                             
  210.                              (**MyShell).Proc[ currProcSlot ].CmdProcPtr = theCommand;
  211. /* create input proc */             
  212.                             if( *stdInFile && needsStdIn )    /* init stdin */
  213.                                  {
  214.                                 (**MyShell).Proc[ currProcSlot ].ProcActive = TRUE;
  215.                                 inProc = GetProcSlot( ShellWh );
  216.                                 (**MyShell).Proc[ currProcSlot ].ProcActive = FALSE;
  217.  
  218.                                 (**MyShell).Proc[ inProc ].argc = 0;
  219.                                 if( inProc == UNKNOWN )        /* no slots left !!! */
  220.                                     {
  221.                                     ShellError( se_noProcSlots );    
  222.                                     return( FALSE );
  223.                                     }
  224.                                     
  225.                                 (**MyShell).Proc[ inProc ].CmdProcPtr = (ProcPtr) StdInProc;
  226.                                 ioOk = (*StdInProc)( PROC_INIT, ShellWh, inProc, stdInFile );
  227.                                     
  228.                                 if( ioOk == FALSE )
  229.                                     parseErr = se_ioRedir;
  230.                                 else
  231.                                     (**MyShell).Proc[ inProc ].ProcActive     = TRUE;
  232.                                 }
  233. /* create output proc */             
  234.                             if( *stdOutFile )    /* init stdout */
  235.                                  {
  236.                                 (**MyShell).Proc[ currProcSlot ].ProcActive = TRUE;
  237.                                 outProc = GetProcSlot( ShellWh );
  238.                                 (**MyShell).Proc[ currProcSlot ].ProcActive = FALSE;
  239.  
  240.                                 (**MyShell).Proc[ outProc ].argc = 0;
  241.                                 if( outProc == UNKNOWN )        /* no slots left !!! */
  242.                                     {
  243.                                     ShellError( se_noProcSlots );    
  244.                                     return( FALSE );
  245.                                     }
  246.                                     
  247.                                 (**MyShell).Proc[ outProc ].CmdProcPtr = (ProcPtr) StdOutProc;
  248.                                 ioOk = (*StdOutProc)( PROC_INIT, ShellWh, outProc, stdOutFile );
  249.                                     
  250.                                 if( ioOk == FALSE )
  251.                                     parseErr = se_ioRedir;
  252.                                 else
  253.                                     (**MyShell).Proc[ outProc ].ProcActive     = TRUE;
  254.                                 }
  255.     
  256.                             if( pipeFromLast && (lastProcSlot != CL_PROCID))
  257.                                 InitProc( ShellWh, currProcSlot, lastProcSlot, outProc, errProc );
  258.                             else
  259.                                 {
  260.                                 InitProc( ShellWh, currProcSlot, inProc, outProc, errProc );
  261.                                 
  262.                                 if( needsStdIn && (parseErr == noErr))
  263.                                     (**MyShell).prompt = 1;
  264.                                 }
  265.  
  266.                             if( tokenType == tkn_separator )
  267.                                 {
  268.                                 /* command was separated on the command line
  269.                                    run the command until it is complete */
  270.                                 
  271.                                 while( (**MyShell).Proc[ currProcSlot ].ProcActive )
  272.                                        ProcMgrIdle( ShellWh );
  273.                                        
  274.                                 outProc = (**MyShell).Proc[ ProcID ].StdOutProcID;
  275.                                 errProc = (**MyShell).Proc[ ProcID ].StdErrProcID;
  276.                                 }
  277.                             
  278.                             /* Set up another proc slot */
  279.                             lastProcSlot = currProcSlot;
  280.                             ProcDataAvail = FALSE;
  281.                             pipeFromLast = pipeToNext;
  282.                             
  283.                             currProcSlot = GetProcSlot( ShellWh );
  284.                             if( currProcSlot == UNKNOWN )
  285.                                 {
  286.                                 ShellError( se_noProcSlots );    
  287.                                 return( FALSE );
  288.                                 }
  289.                             else    /* Initialize the Proc */
  290.                                 {
  291.                                 (**MyShell).Proc[ currProcSlot ].argc = 0;
  292.                                 cmdc             = 0;
  293.                                 
  294.                                 stdInFile[ 0 ]     = '\0';
  295.                                 stdOutFile[ 0 ]    = '\0';
  296.                                 ProcDataAvail    = FALSE;
  297.                                 (**MyShell).StdOutAppend     = FALSE;
  298.                                 
  299.                                 if( tokenType == tkn_separator )
  300.                                     {
  301.                                     lastProcSlot     = CL_PROCID;
  302.                                     pipeFromLast    = FALSE;
  303.                                     pipeToNext        = FALSE;
  304.                                     pipeErr         = FALSE;
  305.                                     }
  306.                                 }
  307.                             }
  308.                         else if( BuiltInCMD( ShellWh, currProcSlot, ProcID, command ))
  309.                             {
  310.                             /* taken care of */
  311.                             }
  312.                         else    /* name could be a script or an application */
  313.                             {
  314.                             int16    refNum;
  315.                             char    str[ 256 ];
  316.                                 
  317.                             strcpy( str, command );
  318.                             CtoPstr( str );
  319.                             
  320.                             
  321.                             refNum = OpenFile( ShellWh, command, 'TEXT', fsRdPerm );
  322.                             
  323.                             if( !refNum )
  324.                                 {
  325.                                 strcpy( str, command );
  326.                                 strcat( str, ".script" );    
  327.                                 refNum = OpenFile( ShellWh, str, 'TEXT', fsRdPerm );
  328.                                 if( refNum )
  329.                                     strcpy( command, str );
  330.                                 }
  331.  
  332.                             if( refNum )
  333.                                 {
  334.                                 int16    ni, na, nc = 0;
  335.                                 char    *cp, *np;
  336.                                 
  337.                                 FSClose( refNum );
  338.                                 
  339.                                 /* save the new command and arguments */
  340.                                 na = (**MyShell).Proc[ currProcSlot ].argc;
  341.                                 
  342.                                 (**MyShell).Proc[ currProcSlot ].argv[ 0 ] = 0;
  343.                                 
  344.                                 cp = command;
  345.                                 while( *cp++ )
  346.                                     nc++;
  347.                                 nc++;
  348.                                 
  349.                                 for( ni = 1; ni < na; ni++ )
  350.                                     {
  351.                                     GetArgv( ShellWh, currProcSlot, ni, str );
  352.                                     
  353.                                     (**MyShell).Proc[currProcSlot].argv[ni] = nc;
  354.                                     
  355.                                     np = str;
  356.                                     while( *cp++ = *np++ )
  357.                                         nc++;
  358.                                     nc++;
  359.                                     }
  360.                                 
  361.                                 for( ni = 0; ni < nc; ni++ )
  362.                                     (**MyShell).Proc[ currProcSlot ].cmdline[ni] = command[ni];
  363.                                 
  364.                                 theCommand = (ProcPtr) DoSCRIPT;
  365.                                 needsStdIn = FALSE;
  366.                                 goto forceCommand;
  367.                                 }
  368.                             else
  369.                                 {
  370.                                 refNum = OpenFile( ShellWh, command, 'APPL', fsRdPerm );
  371.                             
  372.                                 if( refNum )
  373.                                     {
  374.                                     pathType    pt;
  375.                                     OsErr        lerr;
  376.                                     
  377.                                     FSClose( refNum );
  378.                                     /* application */
  379.                                     
  380.                                     if( CanLaunch() == FALSE )
  381.                                         {
  382.                                         procPrintf( ShellWh, ProcID,
  383.                                             "sh : Applications can only be launched under MultiFinder\n" );
  384.                                         }
  385.                                     else
  386.                                         {
  387.                                         pt = SetCurrPath( command );
  388.                                         if( pt == pathIsFile )
  389.                                             {
  390.                                             int16    cv;
  391.                                             int32    cd, cp;
  392.                                             
  393.                                             GetPWDInfo( &cv, &cd, &cp );
  394.                                             strcpy( str, GetLastScan() );
  395.                                             CtoPstr( str );
  396.                                             lerr = DoLaunch( str, cv, cd );
  397.                                             
  398.                                             if( lerr )
  399.                                                 procPrintf( ShellWh, ProcID,
  400.                                                     "sh : can't launch %ps (%d)\n", str, lerr );
  401.                                             }
  402.                                         }
  403.                                         
  404.                                     ResetShellPWD( ShellWh );
  405.                                     }
  406.                                 else
  407.                                     {
  408.                                     char    *sp, *cp;
  409.                                     
  410.                                     sp = cp = command;
  411.                                     while( *cp )
  412.                                         {
  413.                                         if( *cp == '=' )
  414.                                             break;
  415.                                         else
  416.                                             cp++;
  417.                                         }
  418.                                         
  419.                                     if( *cp == '=' )    /* Shell variable, put '\0' over '=' */
  420.                                         {
  421.                                         *cp++ = '\0';
  422.                                         ShellSetVar( ShellWh, sp, cp );
  423.                                         }
  424.                                     else
  425.                                         parseErr = se_unknownCmd;
  426.                                     }
  427.                                 }
  428.                             }
  429.                         }
  430.                     break;
  431.  
  432.                 case    tkn_var            :    /* '$'            */
  433.                 case    tkn_identifier    :    /*                 */
  434.                 case    tkn_digit        :    /* '0-9.'        */
  435.                     {
  436.                     char    *s;
  437.                     char    varName[ 64 ];
  438.                     /* save as argument */
  439.                     
  440.                     if( tokenType == tkn_var )
  441.                         {                        
  442.                         if( cp )
  443.                             {
  444.                             cp = GetShellToken( cp, varName, &tokenType );
  445.                             s = ShellGetVar( ShellWh, varName );
  446.                             }
  447.                         else
  448.                             s = buf;
  449.                         }
  450.                     else
  451.                         s = buf;
  452.                         
  453.                     (**MyShell).Proc[currProcSlot].argv[(**MyShell).Proc[currProcSlot].argc] =
  454.                          cmdc;
  455.             
  456.                     while ( (**MyShell).Proc[currProcSlot].cmdline[cmdc++] = *s++ );
  457.                     (**MyShell).Proc[currProcSlot].argc++;
  458.                     ProcDataAvail = TRUE;
  459.                     }
  460.                     break;
  461.  
  462.                 case    tkn_inputRedirect:    /* '<'            */
  463.                     if( cp )
  464.                         {
  465.                         cp = GetShellToken( cp, stdInFile, &tokenType );
  466.                         if( tokenType != tkn_identifier )
  467.                             parseErr = se_expectFile;
  468.                         }
  469.                     else
  470.                         parseErr = se_expectFile;
  471.                     break;
  472.                     
  473.                 case    tkn_inputFromHere:    /* '<<'            */
  474.                     break;
  475.                 
  476.                 case    tkn_outputAppend:    /* '>>'            */
  477.                     (**MyShell).StdOutAppend = TRUE;
  478.                     
  479.                 case    tkn_outputRedirect:    /* '>'            */
  480.                     if( cp )
  481.                         {
  482.                         cp = GetShellToken( cp, stdOutFile, &tokenType );
  483.                         if( tokenType != tkn_identifier )
  484.                             parseErr = se_expectFile;
  485.                         }
  486.                     else
  487.                         parseErr = se_expectFile;
  488.                     break;
  489.                     
  490.                 case    tkn_comment        :    /* '#'            */
  491.                     {
  492.                     while( cp )
  493.                         {
  494.                         cp = GetShellToken( cp, stdOutFile, &tokenType );
  495.                         if( tokenType == tkn_eol )
  496.                             break;
  497.                         }
  498.                     goto    Execute;
  499.                     }
  500.                     break;
  501.  
  502.                 case    tkn_caseDelimit    :    /* ';;'            */
  503.  
  504.                 case    tkn_leftParen    :    /* '('            */
  505.                 case    tkn_rightParen    :    /* ')'            */
  506.  
  507.  
  508.  
  509.                 case    tkn_singleQuote    :    /* '''            */
  510.                 case    tkn_doubleQuote    :    /* '"'            */
  511.  
  512.                 case    tkn_if            :    /* 'if'            */
  513.                 case    tkn_then        :    /* 'then'        */
  514.                 case    tkn_else        :    /* 'else'        */
  515.                 case    tkn_elif        :    /* 'elif'        */
  516.                 case    tkn_fi            :    /* 'fi'            */
  517.  
  518.                 case    tkn_case        :    /* 'case'        */
  519.                 case    tkn_in            :    /* 'in'            */
  520.                 case    tkn_esac        :    /* 'esac'        */
  521.  
  522.                 case    tkn_for            :    /* 'for'        */
  523.                 case    tkn_while        :    /* 'while'        */
  524.                     
  525.                 case    tkn_until        :    /* 'until'        */
  526.                 case    tkn_do            :    /* 'do'            */
  527.                 case    tkn_done        :    /* 'done'        */
  528.  
  529.                 case    tkn_break        :    /* 'break'        */
  530.                 case    tkn_continue    :    /* 'continue'    */
  531.                 case    tkn_exit        :    /* 'exit'        */
  532.  
  533.                 case    tkn_leftCurl    :    /* '{'            */
  534.                 case    tkn_rightCurl    :    /* '}'            */
  535.                     break;
  536.                     
  537.                 case    tkn_unknown        :
  538.                     break;
  539.                     
  540.                 default    :
  541.                     break;
  542.                 }
  543.             
  544.             if( parseErr )
  545.                 break;
  546.             }        
  547.  
  548.         lastToken = tokenType;
  549.         }
  550. /*
  551.  *    Start execution of any commands
  552.  */
  553.     if( parseErr && verbose )
  554.         {
  555. /*        printf( "%s", (**MyShell).Proc[ currProcSlot ].cmdline ); */
  556.         ShellError( parseErr );
  557.         }
  558.     
  559.     if( lastProcSlot != CL_PROCID )
  560.         ProcMgrIdle( ShellWh );
  561.     
  562.     return( TRUE );
  563. }
  564.  
  565. /*******************************************************************/
  566.  
  567. void        SCRIPTCallBack( WHandle ShellWh, int16 ProcID,
  568.                 char *path, char *last,
  569.                 pathType what, int16 vRefNum, int32 dirID )
  570. {
  571. CInfoPBRec         pb;
  572. char            str[ 256 ];
  573. int16            sRefNum, sErr = noErr, i, argc;
  574. int32            count;
  575. char            *cp;
  576. ShellWindRec    **MyShell = (ShellWindRec **) (**ShellWh).thing;
  577.  
  578.     argc = (**MyShell).Proc[ ProcID ].argc;
  579.     
  580.     if( what != pathIsFile )
  581.         return;
  582.     
  583.     strcpy( str, last );
  584.     CtoPstr( str );
  585.     
  586.     pb.hFileInfo.ioCompletion     = NULL;
  587.     pb.hFileInfo.ioNamePtr         = (StringPtr) str;
  588.     pb.hFileInfo.ioVRefNum         = vRefNum;
  589.     pb.hFileInfo.ioDirID         = dirID;
  590.     pb.hFileInfo.ioFDirIndex     = 0;
  591.     
  592.     sErr = PBHGetFInfo( &pb, FALSE );
  593.     
  594. #ifdef    SDB
  595.     printf( "Script GetInfo Type %lX\n", pb.hFileInfo.ioFlFndrInfo.fdType );
  596. #endif
  597.  
  598.     if( sErr || pb.hFileInfo.ioFlFndrInfo.fdType != 'TEXT' )
  599.         return;
  600.  
  601.     sErr = HOpen( vRefNum, dirID, str, fsRdPerm, &sRefNum );
  602.     PtoCstr( str );
  603.     
  604. #ifdef    SDB
  605.     printf( "Script OpenFile %d\n", sRefNum );
  606. #endif
  607.  
  608.     if( !sErr && sRefNum )
  609.         {
  610. #ifdef    SCRIPTDEBUG
  611.         printf( "Running SCRIPT : '%s'\n", str );
  612. #endif
  613.         i = 0;
  614.         cp = str;
  615.         
  616.         while( !sErr && i < 255 )
  617.             {
  618.             count = 1L;
  619.             sErr = FSRead( sRefNum, &count, cp );
  620.         
  621.             if( !sErr || sErr == eofErr )
  622.                 {
  623.                 if( sErr == eofErr )
  624.                     *cp = '\n';
  625.                 
  626.                 if( *cp == '\r' )
  627.                     *cp = '\n';
  628.                     
  629.                 if( *cp == '\n' || sErr == eofErr )
  630.                     {
  631.                     *++cp = '\0';
  632.                     if( DoSCRIPTLine( ShellWh, ProcID, str ) == FALSE )
  633.                         return;
  634.                     
  635.                     i = 0;
  636.                     cp = str;
  637.                     }
  638.                 else if( *cp == '$' )    /* shell var ? */
  639.                     {
  640.                     sErr = FSRead( sRefNum, &count, cp );
  641.  
  642.                     if( (*cp >= '0') && (*cp <= '9') )        /* substitute the shell var */
  643.                         {
  644.                         int16    argc;
  645.                         char    *sp, argbuf[ 256 ];
  646.                         
  647.                         argc = *cp - '0';
  648.                         
  649.                         if( argc < (**MyShell).Proc[ ProcID ].argc )
  650.                             {
  651.                             GetArgv( ShellWh, ProcID, argc, argbuf );
  652.                             sp = argbuf;
  653.                             while( *sp )
  654.                                 {
  655.                                 *cp = *sp;
  656.                                 cp++;
  657.                                 sp++;
  658.                                 i++;
  659.                                 }
  660.                             }
  661.                         }
  662.                     else if( *cp == '#' )    /* number of arguments */
  663.                         {
  664.                         *cp++ = '0' + argc;
  665.                         }
  666.                     else    /* oops, add the char and continue */
  667.                         {
  668.                         char    cs = *cp;
  669.                         
  670.                         cp--;
  671.                         *cp++ = '$';
  672.                         *cp++ = cs;
  673.                         i+=2;
  674.                         }
  675.                     }
  676.                 else
  677.                     {
  678.                     cp++;
  679.                     i++;
  680.                     }
  681.                 }
  682.             }
  683.         
  684.         FSClose( sRefNum );
  685.         }
  686. }
  687.  
  688. /*******************************************************************/
  689.  
  690. void        SCRIPTFile( WHandle ShellWh, int16 ProcID, char *argument )
  691. {
  692. ShellWindRec    **MyShell;
  693.  
  694.     MyShell = (ShellWindRec **) (**ShellWh).thing;
  695.  
  696. #ifdef    SDB
  697.     printf( "Script ExpandPath %s\n", argument );
  698. #endif
  699.     ScanInit();
  700.     ScanForTYPE( 'TEXT' );
  701.  
  702.      ExpandPath( ShellWh, ProcID, argument, (ProcPtr) SCRIPTCallBack,
  703.             (**MyShell).pwdVRefNum, (**MyShell).pwdDirID );
  704.  
  705.     ScanInit();
  706.     ResetShellPWD( ShellWh );
  707. }
  708.  
  709. /*******************************************************************/
  710.  
  711. Boolean            DoSCRIPT( int16 ProcToken, WHandle ShellWh,
  712.                     int16 ProcID, char *string )
  713. {
  714. int16            i, argc;
  715. char            *cp, argument[ 256 ];
  716. ShellWindRec    **MyShell = (ShellWindRec **) (**ShellWh).thing;
  717.  
  718.     switch( ProcToken )
  719.         {
  720.         case    PROC_INIT    :
  721.             (**MyShell).Proc[ ProcID ].flags = TRUE;
  722.             break;
  723.             
  724.         case    PROC_TERM    :
  725.         case    PROC_BREAK    :
  726.             /* Tell the shell that we're done */
  727.             SendOutToken( ShellWh, ProcID, PROC_BREAK );
  728.             /* Turn ourself off */
  729.             (**MyShell).Proc[ ProcID ].ProcActive = FALSE;
  730.             break;
  731.             
  732.         case    PROC_STDIN    :
  733.             if( (**MyShell).Proc[ ProcID ].flags )
  734.                 {
  735.                 (**MyShell).Proc[ ProcID ].flags = FALSE;        
  736.  
  737.                 /* get arguments */
  738.                 argc = (**MyShell).Proc[ ProcID ].argc;
  739.                 verbose = FALSE;
  740.  
  741. #ifdef    SCRIPTDEBUG
  742.                 verbose = TRUE;
  743. #endif
  744.                 
  745.                 for( i = 1; i < argc; i++ )
  746.                     {
  747.                     GetArgv( ShellWh, ProcID, i, argument );
  748.                     cp = argument;
  749.         
  750.                     if( *cp++ == '-' )
  751.                         while( *cp )
  752.                             switch( *cp++ )
  753.                                 {
  754.                                 case    'v'    :    /* verbose */
  755.                                     verbose = TRUE;
  756.                                     break;
  757.                                 case    'e'    :    /* exit if a command fails */
  758.                                     break;
  759.                                 case    'n'    :    /* read commands without executing them */
  760.                                     break;
  761.                                 case    's'    :    /* s read from stdin */
  762.                                     break;
  763.                                 case    't'    :    /* read and execute one command then exit */
  764.                                     break;
  765.                                 case    'x'    :    /* print commands as executed, with arguments */
  766.                                     break;
  767.                                 }
  768.                     }
  769.  
  770.                 for( i = 0; i < argc; i++ )
  771.                     {
  772.                     GetArgv( ShellWh, ProcID, i, argument );
  773.                     if( i == 0 && strcmp( argument, "script" ) == 0 )
  774.                         continue;
  775.                         
  776.                     if( *argument != '-' )
  777.                         SCRIPTFile( ShellWh, ProcID, argument );
  778.                     }
  779.                 
  780.                 /* Tell the shell that we're done */
  781.                 SendOutToken( ShellWh, ProcID, PROC_BREAK );
  782.                 /* Turn ourself off */
  783.                 (**MyShell).Proc[ ProcID ].ProcActive = FALSE;
  784.                 }
  785.  
  786.             return( FALSE );
  787.         }
  788. }
  789.